<?php
# autoHTML: the dynamic PHP5 library for fast website prototyping
# http://code.google.com/p/autohtml/
#
# Copyright (c) 2010, Shu Zong Chen
# http://freelanceDreams.com/
# All rights reserved. 
# 
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions are met: 
# 
#  * Redistributions of source code must retain the above copyright notice, 
#    this list of conditions and the following disclaimer. 
#  * Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in the 
#    documentation and/or other materials provided with the distribution. 
#  * Neither the name of autoHTML nor the names of its contributors 
#    may be used to endorse or promote products derived from this software 
#    without specific prior written permission. 
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.

	function parseVariable($target){
		$data = explode(":", $target);
		$i = (isset($this->ARRAYi[$data[0]])) ? $this->ARRAYi[$data[0]] : 0;
		if (count($data)==1){
			return $this->TEXT[$data[0]][$i];
		}else{
			$j = false;
			foreach ($data as $k){
				if ($j){
					$j = $j[$k];
				}else{
					$j = $this->TEXT[$data[0]][$i];
				}
			}
		}
		if ($k == "__i"){
			return $this->ARRAYi[$data[0]];
		}
		return $j;
	}

	function go_spider($string, $debug = false, $transform = false){
		//Transform the code into tokens
		$a = preg_split('/(?<!\\\\)%/', $string);
		unset ($string);
		if (sizeof($a)==1){
			//If only 1 token (text only), output it now and save the work
			echo $a[0];
			return true;
		}
		$tokens = array();
		$l = 0;
		$j = 0;
		for($i = 0; $i<count($a); $i++){
			if ($i%2==0){
				if ($a[$i]!=""){
					array_push($tokens, array("cmd"=>"text", "data"=>$a[$i], "level"=>$l));
					$j++;
				}
			}else{
				$b = explode(":", $a[$i], 2);
				switch ($b[0]){
					case "if":
						array_push($tokens, array("cmd"=>"startif", "level"=>$l));
						$l++;
						array_push($tokens, array("cmd"=>$b[0], "data"=>$b[1], "level"=>$l));
						$l++;
						break;
					case "foreach":
						array_push($tokens, array("cmd"=>$b[0], "data"=>$b[1], "level"=>$l));
						$l++;
						array_push($tokens, array("cmd"=>"iterate", "data"=>$b[1], "level"=>$l));
						$l++;
						break;
					case "endeach":
						$l--;
						array_push($tokens, array("cmd"=>"return", "level"=>$l));
						$l--;
						array_push($tokens, array("cmd"=>$b[0], "data"=>$b[1], "level"=>$l));
						break;
					case "elseif":
					case "else":
						array_push($tokens, array("cmd"=>"gotoend", "level"=>$l));
						$l--;
						array_push($tokens, array("cmd"=>$b[0], "data"=>$b[1], "level"=>$l));
						$l++;
						break;
					case "endif":
						$l-=2;
						array_push($tokens, array("cmd"=>$b[0], "data"=>$b[1], "level"=>$l));
						break;
					default:
     				array_push($tokens, array("cmd"=>$b[0], "data"=>$b[1], "level"=>$l));
     				break;
				}
				$j++;
			}
		}
		$a = null;
		array_push($tokens, array("cmd"=>"stop"));
		if ($transfer){
			echo "<pre>";
			print_r($tokens);
			echo "</pre>";
			return true;
		}
		if ($debug){
			echo "<pre>";
			$i = 0;
			foreach ($tokens as $row){
				echo str_pad($i, 3, " ", STR_PAD_LEFT) . ":";
				echo str_repeat(" ", $row["level"]*2) . $row["cmd"] . ":" . rawurlencode($row["data"]);
				echo "\n";
				$i++;
			}
			echo "</pre>";
		}
		$curr_row=0; //This will be used to keep track of the current row
		$run = true;
		while($run){
			switch ($tokens[$curr_row]["cmd"]){
				case "func":
					$a = explode(":", $tokens[$curr_row]["data"], 2);
					if (function_exists($a[0])){
						call_user_func($a[0], $a[1]);
					}else{
						echo "Call to function $a[0] failed.";
					}
					break;
				case "text":
					echo $tokens[$curr_row]["data"];
					break;
				case "var":
					$this->go_spider($this->parseVariable($tokens[$curr_row]["data"]));
					break;
				case "str":
					echo $this->parseVariable($tokens[$curr_row]["data"]);
					break;
				case "file":
					f_loadFile($tokens[$curr_row]["data"]);
					break;
				case "asset":
					$this->go_spider($this->loadAsset($tokens[$curr_row]["data"]));
					break;
				case "form":
					$a = explode(":", $tokens[$curr_row]["data"], 3);
					$b = $this->parseVariable($a[1]. ":" . $a[2]);
					$b = htmlspecialchars($b);
					$c = $a[2];
					switch ($a[0]){
						case "text":
							echo "<input type=\"text\" name=\"{$c}\" value=\"{$b}\" />";
							break;
						case "pass":
							echo "<input type=\"password\" name=\"{$c}\" value=\"{$b}\" />";
							break;
						case "textarea":
							echo "<textarea name=\"{$c}\">$b</textarea>";
							break;
						case "radio":
							$this->ARRAYi["__form_radio_name"] = $c;
							$this->ARRAYi["__form_radio"] = $b;
							break;
						case "endradio":
							break;
						case "select":
							echo "<select name=\"{$c}\">";
							$this->ARRAYi["__form_select"] = $b;
							break;
						case "endselect":
							echo "</select>";
							break;
						case "hidden":
							echo "<input type=\"hidden\" name=\"{$c}\" value=\"{$b}\" />";
							break;
					}
					break;
				case "radio":
					$a = explode(":", $tokens[$curr_row]["data"], 2);
					$b = $this->ARRAYi["__form_radio_name"];
					if ($this->ARRAYi["__form_radio"] == $a[0]){
						echo "<input type=\"radio\" name=\"$b\" value=\"$a[0]\" checked=\"checked\" />{$a[1]}";
					}else{
						echo "<input type=\"radio\" name=\"$b\" value=\"$a[0]\" />{$a[1]}";
					}
					break;
				case "option":
					$a = explode(":", $tokens[$curr_row]["data"], 2);
					if ($this->ARRAYi["__form_select"] == $a[0]){
						echo "<option value=\"$a[0]\" selected=\"selected\">{$a[1]}</option>";
					}else{
						echo "<option value=\"$a[0]\">{$a[1]}</option>";
					}
					break;
				case "if":
				case "elseif":
					$a = explode("==", $tokens[$curr_row]["data"], 2);
					$b = $a[1];
					$a = $this->parseVariable($a[0]);
					$c = false;
					if ($b){
						//If a value is set to be tested for
						if ($a==$b){
							$c = true;
						}
					}else{
						//No value, just test for existence
						// if (isset($this->TEXT[$a])){   //use this if "" resolves as true
						if ($a){							//use this if "" resolves as false
							$c = true;
						}
					}
					$l = $tokens[$curr_row]["level"];
					if (!$c){
						while (true){
							$curr_row++;
							if (!$tokens[$curr_row] || $tokens[$curr_row]["level"] <= $l){
								$curr_row--;
								break;
							}
						}
					}
					break;
				case "foreach":
					$name = $tokens[$curr_row]["data"];
					$this->ARRAYi[$name] = -1;
					break;
				case "iterate":
					$name = $tokens[$curr_row]["data"];
					$this->ARRAYi[$name]++;
					if ($this->TEXT[$name][$this->ARRAYi[$name]]){
						//Proceed!
					}else{
						$l = $tokens[$curr_row]["level"];
						while (true){
							$curr_row++;
							if (!$tokens[$curr_row] || $tokens[$curr_row]["level"] <= $l){
								break;
							}
						}
					}
					break;
				case "gotoend":
					$l = $tokens[$curr_row]["level"]-2;
					while (true){
						$curr_row++;
						if (!$tokens[$curr_row] || $tokens[$curr_row]["level"] <= $l){
							$curr_row--;
							break;
						}
					}
					break;
				case "return":
					$l = $tokens[$curr_row]["level"];
					while (true){
						$curr_row--;
						if (!$tokens[$curr_row] || $tokens[$curr_row]["level"] == $l){
							$curr_row--;
							break;
						}
					}
					break;
				case "":
				case "stop":
					$run = false;
					break;
				case "else":
				case "startif":
				case "endif":
				case "endeach":
				case "null":
					//Pass!
					break;
				case "parse":
					break;
				default:
					echo "Don't know what to do with {$tokens[$curr_row]["cmd"]}({$tokens[$curr_row]["data"]})\n";
					break;
			}
			$curr_row++;
			if ($debug){
				echo "<br />goto $curr_row &nbsp;";
			}
		}
	}